//
//  Thread.h
//  多线程
//
//  Created by Toj on 8/8/21.
//

https://www.jianshu.com/p/02f438df17ef
https://www.jianshu.com/p/2d57c72016c6

#pragma mark - 问题
1. 概念问题
2. 多线程有哪些?
3. NSOpration 与 GCD
4. 多线程交互
5. 多线程应用
6. 多线程会出现哪些问题

#pragma mark - 1. 概念问题
1. 任务: 执行的内容,// { 内部的代码 }

2. 调用方式
2.1 -> 同步: 不具备开启线程, 在当前线程中执行
2.2 -> 异步: 具备开启新线程, 但不一定开启线程, 看所在队列类型.

3. 队列: 任务执行需要一个放到队列里, 才能保证有效的执行
3.1 -> 串行: 多个任务从头到尾依次执行. 必须等待上一个【任务】结束才能执行下一个【任务】
场景: 类似于排队打饭, 在不插队的前提下, 有序执行
线程数: '至多'开启一个子线程, 为什么'至多'(同一个队列, 不同队列不考虑)
*** 主队列也是串行队列
当主线程内: "主队" + 同步 = 崩溃, 死锁, 详情请看【锁.h】
当主线程内: "主队" + 异步 = 不开启子线程
当主线程内: "串行" + 同步 = 不开启子线程
当主线程内: "串行" + 异步 = '至多'开启一个子线程

同步线程内: "主队" + 同步 = 崩溃, 死锁, 详情请看【锁.h】
同步线程内: "主队" + 异步 = 不开启子线程
// 如果"串行"用的跟"同步线程内的串行队列"一致也会造成死锁, 同"主+同"一样
同步线程内: "串行" + 同步 = 不开启子线程
同步线程内: "串行" + 异步 = '至多'开启一个子线程

异步线程内: "主队" + 同步 = 不开启子线程
异步线程内: "主队" + 异步 = 不开启子线程
异步线程内: "串行" + 同步 = 不开启子线程
异步线程内: "串行" + 异步 = '至多'开启一个子线程

3.2 -> 并行: 多个任务不需要等待一起执行, 结束也不一定哪个任务先执行完
场景: 100米赛跑, 一起跑, 不一定哪个先到达终点
线程数: 0-n
当主线程内: "并行" + 同步 = 不开启子线程
当主线程内: "并行" + 异步 = '至少'开启一个子线程

同步线程内: "并行" + 同步 = 不开启子线程
同步线程内: "并行" + 异步 = '至少'开启一个子线程

异步线程内: "并行" + 同步 = 不开启子线程
异步线程内: "并行" + 异步 = '至少'开启一个子线程


#pragma mark - 2. 多线程有哪些?
1. p_thread
2. NSThread
3. NSOpration
4. GCD

#pragma mark - 3. NSOpration 与 GCD
GCD:
1. c的一套api
2. 充分利用多核技术, 实现并行操作(多核处理器)， 单核还是并发操作
3. 线程数只能由线程池做决定, 无法做到限制数量

NSOperation:
1. 基于GCD的一个实现
2. 面向对象的
3. 比GCD多了一些功能实现
4. 控制开启线程数
5. 他是一个抽象类, 必须用其子类/ 自定义实现方式


#pragma mark - 5. 多线程应用
1. 解决timer 不准确的问题
把timer添加到子线程中runlooop中, 回到主线程更新UI
- (void)initThread {
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadHandle) object:nil];
    [thread start];
}

- (void)threadHandle {
    @autoreleasepool
    {
        [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(didTimer) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] run];
    }
}

2. 并发事件, e.g.网络请求
3. 复杂逻辑在子线程中执行, 回到主线程更新UI
4. 大文件多个子线程下载
 需要控制好当前下载的进度, 断点续传当前线程已经下载完, 再开始就不需要下载了
https://www.cnblogs.com/lingzeng/p/4008812.html
5. 检测卡顿情况
开启子线程监听时间变化, 通过信号量实现监听时间的差值
6. 数据同步, 本地数据同步服务器
7. 音视频处理
8. 数据库操作大量数据


#pragma mark - 6. 多线程会出现哪些问题
1. 数据竞争
2. 死锁
3. 大量内存消耗, CPU消耗过大, 手机发热






/**
 
 // 线程数: '至多'开启一个子线程, 为什么'至多'
 *** 主队列也是串行队列
 当主线程内: "主队" + 同步 = 崩溃, 死锁, 详情请看【锁.h】
 当主线程内: "主队" + 异步 = 不开启子线程

 同步线程内: "串行" + 同步 = 不开启子线程
 同步线程内: "串行" + 异步 = 不开启子线程

 异步线程内: "串行" + 异步 = '至多'开启一个子线程
 异步线程内: "串行" + 同步 = 不开启子线程

 3.2 -> 并行: 多个任务不需要等待一起执行, 结束也不一定哪个任务先执行完
 场景: 100米赛跑, 一起跑, 不一定哪个先到达终点
 线程数: '至少'开启一个子线程, 为什么'至少'
 当主线程内: "并行" + 同步 = '至多'开启一个子线程
 当主线程内: "并行" + 异步 = '至少'开启一个子线程

 同步线程内: "并行" + 同步 = '至多'开启一个子线程
 同步线程内: "并行" + 异步 = '至少'开启一个子线程

 异步线程内: "并行" + 同步 = '至多'开启一个子线程
 异步线程内: "并行" + 异步 = '至少'开启一个子线程
 
 
 */
